package clusters

import (
	"github.com/hashicorp/memberlist"
	"net"
	"fmt"
	"strconv"
	"haproxy-mgr-go/models"
	"strings"
	"time"
	"haproxy-mgr-go/models/nodes"
)


var Members map[string]string

func StartServ() *memberlist.Memberlist {
	list, err := memberlist.Create(memberlist.DefaultLocalConfig())
	if err != nil {
		panic("Failed to create memberlist: " + err.Error())
	}

	return list
}

func CheckNode(nodes *models.Nodes) bool {
	fmt.Println("checkNode")
	valid := false

	fmt.Println(ensurePort(nodes.ClusterListnerAddress, 7496))

	addrs := strings.Split(ensurePort(nodes.ClusterListnerAddress, 7946), ":")
	if len(addrs) == 2 {
		hostIP := net.ParseIP(addrs[0])
		port,_ := strconv.Atoi(addrs[1])

		tcpAddr := net.TCPAddr{
			IP:   hostIP,
			Port: port,
		}

		conn, err := net.DialTCP("tcp", nil, &tcpAddr)

		if err == nil {
			valid = true
			conn.Close()
		}
	}


	fmt.Println(valid)

	return valid
}

func GetMembers(ml *memberlist.Memberlist)  {
	for  {
		for _, member := range ml.Members() {
			fmt.Printf("Member: %s %s\n", member.Name, member.Addr)
		}

		time.Sleep(time.Second * 10)
	}

}

func SyncMembers(ml *memberlist.Memberlist)  {
	for  {
		time.Sleep(time.Second * 10)

		Members = make(map[string]string)

		for _, member := range ml.Members() {
			Members[member.Name] = member.Addr.String()
		}

		var nodeList []models.Nodes

		for _, member:= range ml.Members() {
			node := models.Nodes{}
			node.Name = member.Name
			node.ClusterListnerAddress = member.Addr.String()
			nodeList = append(nodeList, node)
		}

		nodes.ReplaceAll(nodeList)
	}

}

// hasPort is given a string of the form "host", "host:port", "ipv6::address",
// or "[ipv6::address]:port", and returns true if the string includes a port.
func hasPort(s string) bool {
	// IPv6 address in brackets.
	if strings.LastIndex(s, "[") == 0 {
		return strings.LastIndex(s, ":") > strings.LastIndex(s, "]")
	}

	// Otherwise the presence of a single colon determines if there's a port
	// since IPv6 addresses outside of brackets (count > 1) can't have a
	// port.
	return strings.Count(s, ":") == 1
}

// ensurePort makes sure the given string has a port number on it, otherwise it
// appends the given port as a default.
func ensurePort(s string, port int) string {
	if hasPort(s) {
		return s
	}

	// If this is an IPv6 address, the join call will add another set of
	// brackets, so we have to trim before we add the default port.
	s = strings.Trim(s, "[]")
	s = net.JoinHostPort(s, strconv.Itoa(port))
	return s
}

func GetMemberlist() map[string]string {
	return Members
}